package com;

import lombok.Data;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;

/**
 * 企业级校验框架 - 完整实现
 * 支持：单字段校验、跨字段校验、自定义校验器、表达式校验
 */
public class ValidationFramework {
    public enum ValidateRuleType {
        NONE,
        REQUIRED,
        LENGTH,
        REGEX,
        CUSTOM,
        MIN, EXPRESSION
    }
    // ==================== 核心注解定义 ====================
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface ValidateRule {
        ValidateRuleType type() default ValidateRuleType.NONE;

        int min() default Integer.MIN_VALUE;

        int max() default Integer.MAX_VALUE;

        String pattern() default "";

        String message() default "";

        String errorCode() default "";

        Class<? extends ValidatorFunction> customValidator() default ValidatorFunction.None.class;
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface FieldChecks {
        FieldCheck[] value();
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Repeatable(FieldChecks.class)
    public @interface FieldCheck {
        String[] fields();

        String condition() default "";

        String expression() default "";

        String message();

        String errorCode() default "INVALID_COMBINATION";
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface CrossFieldValidation {
        Class<? extends GroupValidator>[] validators() default {};
    }

    // ==================== 校验接口定义 ====================
    public interface ValidatorFunction {
        ValidationResult validate(String fieldName, Object value, Object object);

        class None implements ValidatorFunction {
            @Override
            public ValidationResult validate(String fieldName, Object value, Object object) {
                return ValidationResult.valid();
            }
        }
    }

    public interface GroupValidator {
        List<ValidationResult> validate(Object obj);
    }

    public interface ExpressionValidator {
        boolean validate(Object obj);
    }

    // ==================== 校验结果类 ====================
    @Data
    public static class ValidationResult {
        private String field;
        private List<String> fields;
        private String message;
        private String errorCode;

        public boolean isValid() {
            return (field == null || field.isEmpty()) &&
                    (fields == null || fields.isEmpty());
        }

        // 静态工厂方法
        public static ValidationResult valid() {
            return new ValidationResult();
        }

        public static ValidationResult error(String field, String message) {
            ValidationResult result = new ValidationResult();
            result.setField(field);
            result.setMessage(message);
            return result;
        }

        public static ValidationResult error(String field, String message, String errorCode) {
            ValidationResult result = new ValidationResult();
            result.setField(field);
            result.setMessage(message);
            result.setErrorCode(errorCode);
            return result;
        }

        public static ValidationResult multiFieldError(List<String> fields, String message, String errorCode) {
            ValidationResult result = new ValidationResult();
            result.setFields(fields);
            result.setMessage(message);
            result.setErrorCode(errorCode);
            return result;
        }
    }

    // ==================== 校验引擎核心 ====================
    public static class ValidationEngine {
        public static List<ValidationResult> validate(Object object) {
            List<ValidationResult> results = new ArrayList<>();

            // 1. 单字段校验
            results.addAll(validateSingleFields(object));

            // 2. 跨字段校验
            results.addAll(validateCrossFieldChecks(object));

            // 3. 自定义组合校验
            results.addAll(validateGroupValidators(object));

            return results.stream()
                    .filter(r -> !r.isValid())
                    .collect(Collectors.toList());
        }

        private static List<ValidationResult> validateSingleFields(Object obj) {
            List<ValidationResult> errors = new ArrayList<>();
            Class<?> clazz = obj.getClass();

            for (Field field : clazz.getDeclaredFields()) {
                ValidateRule rule = field.getAnnotation(ValidateRule.class);
                if (rule != null) {
                    try {
                        field.setAccessible(true);
                        Object value = field.get(obj);
                        errors.addAll(validateField(field.getName(), value, obj, rule));
                    } catch (IllegalAccessException e) {
                        errors.add(ValidationResult.error(field.getName(), "字段访问失败: " + e.getMessage()));
                    }
                }
            }
            return errors;
        }

        private static List<ValidationResult> validateField(String fieldName, Object value, Object obj, ValidateRule rule) {
            List<ValidationResult> errors = new ArrayList<>();

            // 必填校验
            if (ValidateRuleType.REQUIRED == rule.type()) {
                if (value == null || (value instanceof String && ((String) value).isEmpty())) {
                    String msg = rule.message().isEmpty() ? fieldName + "不能为空" : rule.message();
                    String code = rule.errorCode().isEmpty() ? "REQUIRED" : rule.errorCode();
                    errors.add(ValidationResult.error(fieldName, msg, code));
                }
            }

            // 长度校验
            if ("LENGTH".equals(rule.type()) && value instanceof String) {
                int length = ((String) value).length();
                if (length < rule.min() || length > rule.max()) {
                    String msg = rule.message().isEmpty() ?
                            fieldName + "长度必须在" + rule.min() + "到" + rule.max() + "之间" :
                            rule.message();
                    String code = rule.errorCode().isEmpty() ? "LENGTH" : rule.errorCode();
                    errors.add(ValidationResult.error(fieldName, msg, code));
                }
            }

            // 正则校验
            if ("REGEX".equals(rule.type()) && value instanceof String && !rule.pattern().isEmpty()) {
                if (!value.toString().matches(rule.pattern())) {
                    String msg = rule.message().isEmpty() ?
                            fieldName + "格式不正确" :
                            rule.message();
                    String code = rule.errorCode().isEmpty() ? "REGEX" : rule.errorCode();
                    errors.add(ValidationResult.error(fieldName, msg, code));
                }
            }

            // 自定义校验函数
            if (!rule.customValidator().equals(ValidatorFunction.None.class)) {
                try {
                    ValidatorFunction validator = rule.customValidator().getDeclaredConstructor().newInstance();
                    ValidationResult result = validator.validate(fieldName, value, obj);
                    if (!result.isValid()) {
                        errors.add(result);
                    }
                } catch (Exception e) {
                    errors.add(ValidationResult.error(fieldName, "自定义校验器执行失败: " + e.getMessage()));
                }
            }

            return errors;
        }

        private static List<ValidationResult> validateCrossFieldChecks(Object obj) {
            List<ValidationResult> errors = new ArrayList<>();
            Class<?> clazz = obj.getClass();

            // 获取所有FieldCheck注解
            List<FieldCheck> checks = getFieldCheckAnnotations(clazz);

            for (FieldCheck check : checks) {
                try {
                    if (!check.condition().isEmpty()) {
                        errors.addAll(validateConditionBasedCheck(obj, check));
                    } else if (!check.expression().isEmpty()) {
                        errors.addAll(validateExpressionBasedCheck(obj, check));
                    }
                } catch (Exception e) {
                    errors.add(ValidationResult.multiFieldError(
                            Arrays.asList(check.fields()),
                            "跨字段校验失败: " + e.getMessage(),
                            "CROSS_FIELD_ERROR"
                    ));
                }
            }

            return errors;
        }

        private static List<ValidationCheck> parseCondition(String condition, List<String> fields) {
            // 简化实现 - 实际生产应更全面
            List<ValidationCheck> checks = new ArrayList<>();

            switch (condition.toUpperCase()) {
                case "EQUALS":
                    for (int i = 1; i < fields.size(); i++) {
                        checks.add(new EqualsCheck(fields.get(0), fields.get(i)));
                    }
                    break;

                case "NOTEQUALS":
                    for (int i = 1; i < fields.size(); i++) {
                        checks.add(new NotEqualsCheck(fields.get(0), fields.get(i)));
                    }
                    break;

                case "GREATERTHAN":
                    if (fields.size() == 2) {
                        checks.add(new GreaterThanCheck(fields.get(0), fields.get(1)));
                    }
                    break;

                case "LESSTHAN":
                    if (fields.size() == 2) {
                        //checks.add(new LessThanCheck(fields.get(0), fields.get(1)));
                    }
                    break;

                case "CONTAINS":
                    if (fields.size() == 2) {
                        //checks.add(new ContainsCheck(fields.get(0), fields.get(1)));
                    }
                    break;

                case "REQUIREDIF":
                    if (fields.size() == 2) {
                        //checks.add(new RequiredIfCheck(fields.get(0), fields.get(1)));
                    }
                    break;

                default:
                    throw new IllegalArgumentException("不支持的校验条件: " + condition);
            }

            return checks;
        }

        private static List<ValidationResult> validateConditionBasedCheck(Object obj, FieldCheck check) {
            List<ValidationResult> errors = new ArrayList<>();
            List<ValidationCheck> validationChecks = parseCondition(check.condition(), Arrays.asList(check.fields()));

            for (ValidationCheck vc : validationChecks) {
                if (!vc.validate(obj)) {
                    errors.add(ValidationResult.multiFieldError(
                            vc.getFields(),
                            check.message(),
                            check.errorCode()
                    ));
                }
            }

            return errors;
        }

        private static List<ValidationResult> validateExpressionBasedCheck(Object obj, FieldCheck check) {
            List<ValidationResult> errors = new ArrayList<>();

            try {
                ExpressionValidator validator = ExpressionEngine.compile(check.expression(), check.fields());
                if (!validator.validate(obj)) {
                    errors.add(ValidationResult.multiFieldError(
                            Arrays.asList(check.fields()),
                            check.message(),
                            check.errorCode()
                    ));
                }
            } catch (ExpressionException e) {
                errors.add(ValidationResult.multiFieldError(
                        Arrays.asList(check.fields()),
                        "表达式错误: " + e.getMessage(),
                        "EXPRESSION_ERROR"
                ));
            }

            return errors;
        }

        private static List<FieldCheck> getFieldCheckAnnotations(Class<?> clazz) {
            List<FieldCheck> checks = new ArrayList<>();

            // 处理单个注解
            FieldCheck[] singleAnnotations = clazz.getAnnotationsByType(FieldCheck.class);
            if (singleAnnotations != null) {
                checks.addAll(Arrays.asList(singleAnnotations));
            }

            // 处理包含多个注解的容器
            FieldChecks container = clazz.getAnnotation(FieldChecks.class);
            if (container != null) {
                checks.addAll(Arrays.asList(container.value()));
            }

            return checks;
        }

        private static List<ValidationResult> validateGroupValidators(Object obj) {
            List<ValidationResult> errors = new ArrayList<>();
            CrossFieldValidation annotation = obj.getClass().getAnnotation(CrossFieldValidation.class);

            if (annotation != null) {
                for (Class<? extends GroupValidator> validatorClass : annotation.validators()) {
                    try {
                        GroupValidator validator = validatorClass.getDeclaredConstructor().newInstance();
                        errors.addAll(validator.validate(obj));
                    } catch (Exception e) {
                        errors.add(ValidationResult.error(
                                "VALIDATOR",
                                "组合校验器失败: " + e.getMessage(),
                                "GROUP_VALIDATOR_ERROR"
                        ));
                    }
                }
            }

            return errors;
        }
    }

    // ==================== 校验检查基类和实现 ====================
    public abstract static class ValidationCheck {
        protected final String field1;
        protected final String field2;

        public ValidationCheck(String field1, String field2) {
            this.field1 = field1;
            this.field2 = field2;
        }

        public List<String> getFields() {
            return Arrays.asList(field1, field2);
        }

        public abstract boolean validate(Object obj);

        protected Object getValue(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        }
    }

    public static class EqualsCheck extends ValidationCheck {
        public EqualsCheck(String field1, String field2) {
            super(field1, field2);
        }

        @Override
        public boolean validate(Object obj) {
            try {
                Object val1 = getValue(obj, field1);
                Object val2 = getValue(obj, field2);
                return Objects.equals(val1, val2);
            } catch (Exception e) {
                return false;
            }
        }
    }

    public static class NotEqualsCheck extends ValidationCheck {
        public NotEqualsCheck(String field1, String field2) {
            super(field1, field2);
        }

        @Override
        public boolean validate(Object obj) {
            try {
                Object val1 = getValue(obj, field1);
                Object val2 = getValue(obj, field2);
                return !Objects.equals(val1, val2);
            } catch (Exception e) {
                return false;
            }
        }
    }

    public static class GreaterThanCheck extends ValidationCheck {
        public GreaterThanCheck(String field1, String field2) {
            super(field1, field2);
        }

        @Override
        public boolean validate(Object obj) {
            try {
                Object val1 = getValue(obj, field1);
                Object val2 = getValue(obj, field2);

                if (!(val1 instanceof Comparable) || !(val2 instanceof Comparable)) {
                    return false;
                }

                @SuppressWarnings("unchecked")
                Comparable<Object> comp1 = (Comparable<Object>) val1;
                return comp1.compareTo(val2) > 0;
            } catch (Exception e) {
                return false;
            }
        }
    }

    // 类似实现其他校验检查...

    // ==================== 表达式引擎 ====================
    public static class ExpressionEngine {
        public static ExpressionValidator compile(String expression, String[] fields) throws ExpressionException {
            return obj -> {
                try {
                    ExpressionEvaluator evaluator = new ExpressionEvaluator();

                    // 设置字段值
                    for (String field : fields) {
                        Object value = getFieldValue(obj, field);
                        evaluator.setVariable(field, value);
                    }

                    // 评估表达式
                    return evaluator.evaluateBooleanExpression(expression);
                } catch (Exception e) {
                    throw new ExpressionException("表达式执行失败: " + e.getMessage(), e);
                }
            };
        }

        private static Object getFieldValue(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        }
    }

    public static class ExpressionEvaluator {
        private final Map<String, Object> variables = new HashMap<>();

        public void setVariable(String name, Object value) {
            variables.put(name, value);
        }

        public boolean evaluateBooleanExpression(String expression) {
            try {
                // 简单实现 - 实际应使用安全表达式解析
                return evaluate(expression);
            } catch (Exception e) {
                throw new ExpressionException("表达式求值失败: " + e.getMessage(), e);
            }
        }

        private boolean evaluate(String expression) {
            if (expression == null || expression.isEmpty()) return false;

            // 处理基本操作
            if (expression.contains("==")) {
                String[] parts = expression.split("==");
                Object left = resolveValue(parts[0].trim());
                Object right = resolveValue(parts[1].trim());
                return Objects.equals(left, right);
            }

            if (expression.contains("!=")) {
                String[] parts = expression.split("!=");
                Object left = resolveValue(parts[0].trim());
                Object right = resolveValue(parts[1].trim());
                return !Objects.equals(left, right);
            }

            if (expression.contains(">=")) {
                String[] parts = expression.split(">=");
                double left = toNumber(resolveValue(parts[0].trim()));
                double right = toNumber(resolveValue(parts[1].trim()));
                return left >= right;
            }

            // 其他操作符处理...

            // 处理逻辑操作
            if (expression.contains("&&")) {
                String[] parts = expression.split("&&");
                for (String part : parts) {
                    if (!evaluate(part.trim())) return false;
                }
                return true;
            }

            if (expression.contains("||")) {
                String[] parts = expression.split("\\|\\|");
                for (String part : parts) {
                    if (evaluate(part.trim())) return true;
                }
                return false;
            }

            // 默认处理
            Object value = resolveValue(expression);
            if (value instanceof Boolean) {
                return (Boolean) value;
            }
            return value != null;
        }

        private Object resolveValue(String expr) {
            if (expr.startsWith("#")) {
                String varName = expr.substring(1);
                return variables.get(varName);
            }

            if ("true".equalsIgnoreCase(expr)) return true;
            if ("false".equalsIgnoreCase(expr)) return false;

            try {
                return Double.parseDouble(expr);
            } catch (NumberFormatException e) {
                // 不是数字
            }

            if (expr.startsWith("\"") && expr.endsWith("\"") && expr.length() > 1) {
                return expr.substring(1, expr.length() - 1);
            }

            return expr;
        }

        private double toNumber(Object value) {
            if (value instanceof Number) {
                return ((Number) value).doubleValue();
            }
            throw new ExpressionException("无法转换为数字: " + value);
        }
    }

    public static class ExpressionException extends RuntimeException {
        public ExpressionException(String message, Throwable cause) {
            super(message, cause);
        }

        public ExpressionException(String message) {
            super(message);
        }
    }

    // ==================== 校验器助手类 ====================
    public static class Validators {
        // 预设验证规则

        // 必填校验
        public static ValidationResult required(Object value, String field, String message) {
            if (value == null || (value instanceof String && ((String) value).isEmpty())) {
                return ValidationResult.error(field, message, "REQUIRED");
            }
            return ValidationResult.valid();
        }

        // 最小值校验
        public static ValidationResult minValue(Number value, int min, String field, String message) {
            if (value != null && value.doubleValue() < min) {
                return ValidationResult.error(field, message, "MIN_VALUE");
            }
            return ValidationResult.valid();
        }

        // 日期顺序校验
        public static ValidationResult dateOrder(Date start, Date end, String startField, String endField) {
            if (start != null && end != null && start.after(end)) {
                return ValidationResult.multiFieldError(
                        Arrays.asList(startField, endField),
                        endField + "必须晚于" + startField,
                        "DATE_ORDER"
                );
            }
            return ValidationResult.valid();
        }

        // 密码匹配校验
        public static ValidationResult passwordMatch(String password, String confirm, String field) {
            if (password != null && !password.equals(confirm)) {
                return ValidationResult.multiFieldError(
                        Arrays.asList(field, field + "Confirm"),
                        "两次输入的密码不一致",
                        "PASSWORD_MATCH"
                );
            }
            return ValidationResult.valid();
        }
    }

    // 用户注册请求对象
    @FieldChecks({
            @FieldCheck(fields = {"password", "passwordConfirm"}, condition = "EQUALS", message = "两次密码输入不一致"),
            @FieldCheck(fields = {"birthDate", "registrationDate"},
                    expression = "#birthDate.before(#registrationDate)",
                    message = "出生日期必须早于注册日期")
    })
    @Data
    public static class UserRegistrationRequest {
        @ValidateRule(type = ValidateRuleType.REQUIRED, message = "用户名不能为空")
        private String username;

        @ValidateRule(type = ValidateRuleType.REGEX, pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).{8,}$",
                message = "密码必须包含大小写字母和数字")
        private String password;

        private String passwordConfirm;

        @ValidateRule(customValidator = AgeValidator.class)
        private int age;

        private Date birthDate;
        private Date registrationDate;

        // 自定义校验器
        public static class AgeValidator implements ValidatorFunction {
            @Override
            public ValidationResult validate(String fieldName, Object value, Object object) {
                int age = (int) value;
                if (age < 18) {
                    return ValidationResult.error(fieldName, "必须年满18岁", "MIN_AGE");
                }
                return ValidationResult.valid();
            }
        }
    }

    // 订单处理请求对象
    @CrossFieldValidation(validators = OrderRequest.OrderTotalValidator.class)
    @Data
    public class OrderRequest {
        @ValidateRule(type = ValidateRuleType.REQUIRED, message = "用户ID不能为空")
        private String userId;

        @ValidateRule(type =  ValidateRuleType.REQUIRED, message = "商品列表不能为空")
        private List<String> items;

        @ValidateRule(type =  ValidateRuleType.MIN, min = 0, message = "总金额必须大于0")
        private double totalAmount;

        private double discountRate;

        // 组合校验器
        public static class OrderTotalValidator implements GroupValidator {
            @Override
            public List<ValidationResult> validate(Object obj) {
                if (obj instanceof OrderRequest) {
                    OrderRequest request = (OrderRequest) obj;
                    if (request.getItems() != null &&
                            request.getTotalAmount() < request.getItems().size() * 10) {
                        return Collections.singletonList(
                                ValidationResult.multiFieldError(
                                        Arrays.asList("totalAmount", "items"),
                                        "订单总额不符合最小商品单价要求",
                                        "MIN_ORDER_TOTAL"
                                )
                        );
                    }
                }
                return Collections.emptyList();
            }
        }
    }


    public static void main(String[] args) {
        // 创建用户注册请求
        UserRegistrationRequest userReq = new UserRegistrationRequest();
        userReq.setUsername("john");
        userReq.setPassword("ValidPass1");
        userReq.setPasswordConfirm("DifferentPass");
        userReq.setAge(16);
        userReq.setBirthDate(new Date());
        userReq.setRegistrationDate(new Date(System.currentTimeMillis() - 100000));

        // 执行校验
        List<ValidationResult> userErrors = ValidationEngine.validate(userReq);

        // 输出结果
        if (userErrors.isEmpty()) {
            System.out.println("用户注册信息校验通过");
        } else {
            System.out.println("用户注册信息校验失败:");
            userErrors.forEach(e -> {
                if (e.getFields() != null) {
                    System.out.printf(" - 字段组合 %s: %s (错误码: %s)%n",
                            e.getFields(), e.getMessage(), e.getErrorCode());
                } else {
                    System.out.printf(" - 字段 %s: %s (错误码: %s)%n",
                            e.getField(), e.getMessage(), e.getErrorCode());
                }
            });
        }

    }

}